<?php
/**
 * <pre>
 * <b>RUBIK IT Solution & Development ltd.</b>
 *
 * PROJECT      : rubik-base
 * COPYRIGHT    : 2008
 * ------------------------------------------------------
 * 
 * [GENERAL INFO OF THIS FILE] 
 *
 * </pre>
 * 
 * @version 		1.5
 * @author			Dang Nhon Hoa <HoaDN@rubik.com.vn>
 * @access			public
 * @package			rubik.base.dbo
 *
 * Created on	: May 5, 2008
 */
RCoreImporter::cls("dbo.RubikDBInfo" );
RCoreImporter::cls("helper.RStringHelper" );

/**
 * The abstract class of RUBIK for management the Database Object
 *
 */
class RubikDBFactory {
	
	/**
	 * Get the DB info
	 *
	 * @return array
	 */
	function &_getBDInfoArray() {
		static $dbInfoArray;
		if (! is_array ( $dbInfoArray )) {
			$dbInfoArray = array ();
		}
		return $dbInfoArray;
	}
	
	/**
	 * Get the DBInfo of a RubikDB object
	 *
	 * @param AbstractRubikDBObject $rubikDBO
	 * @return RubikDBInfo
	 */
	function &getDBInfo($rubikDBO) {
		$dbArray = &RubikDBFactory::_getBDInfoArray ();
		
		$dbInfo = null;
		if (is_string ( $rubikDBO )) {
			$clsName = $rubikDBO;
			$dbInfo = $dbArray [$rubikDBO];
		} else {
			$clsName = get_class ( $rubikDBO );
			$dbInfo = $dbArray [$clsName];
		}
		return $dbInfo;
	}
	
	/**
	 * Set a dbInfo coresponding to a rubikDBO
	 * WARNING: becarefull when using this function
	 *
	 * @param AbstractRubikDBObject $rubikDBO
	 * @param RubikDBInfo $dbInfo
	 */
	function setDBInfo($rubikDBO, &$dbInfo) {
		$dbArray = &RubikDBFactory::_getBDInfoArray ();
		$clsName = get_class ( $rubikDBO );
		$dbArray [$clsName] = &$dbInfo;
	}
	
	/**
	 * Set default value for RubikDB object
	 *
	 * @param AbstractRubikDBObject $rubikDBO
	 * @return AbstractRubikDBObject
	 */
	function setDefaultValue(&$rubikDBO) {
		$dbInfo = RubikDBFactory::getDBInfo ( $rubikDBO );
		$dbInfo->setDefaultValue ( $rubikDBO );
		return $rubikDBO;
	}
	
	/**
	 * Set all values into null.
	 *
	 * @param AbstractRubikDBObject $rubikDBO
	 * @return AbstractRubikDBObject
	 */
	function setAllNullValues(&$rubikDBO) {
		$dbInfo = RubikDBFactory::getDBInfo ( $rubikDBO );
		$dbInfo->setNullAllValues ( $rubikDBO );
		return $rubikDBO;
	}
	
	/**
	 * Set all empty string into null value
	 *
	 * @param AbstractRubikDBObject $rubikDBO
	 * @return AbstractRubikDBObject
	 */
	function setEmptyToNull(&$rubikDBO) {
		$dbInfo = RubikDBFactory::getDBInfo ( $rubikDBO );
		$dbInfo->setEmptyToNull ( $rubikDBO );
		return $rubikDBO;
	}
	
	/**
	 * get where clause with the current criteria object
	 * 
	 * @param AbstractRubikDBObject $rubikDBO
	 * @param string $combileCondition (AND/OR) the TEXT to combine 2 condition. Default: "AND"
	 * @param boolean $ignoreNull	where clause will created with the null value if $ignoreNull = false
	 * @param string $compareKey the key for compare. Ex: "like", "=", ">",...
	 * @param string $prefix the prefix of like clause Ex: "%"
	 * @param string $subfix the subfix of like clause Ex: "*"
	 * 
	 * @return WHERE clause
	 */
	function createWhereClause($rubikDBO, $combineCondition = "AND", $ignoreNull = true, $compareKey = "like", $prefix = "", $subfix = "") {
		$compareKey = strtoupper ( $compareKey );
		
		$fmtsql = " WHERE %s";
		$dbInfo = RubikDBFactory::getDBInfo ( $rubikDBO );
		$fieldList = $dbInfo->getFieldList ( $rubikDBO, $ignoreNull, true );
		
		$compareKey = strtoupper ( $compareKey );
		foreach ( $fieldList as $dbField ) {
			$compare = $compareKey;
			$fieldName = $dbField->fieldName;
			$val = $rubikDBO->$fieldName;
			$val = $dbField->prepareDataForDB ( $val );
			// special treat for SYM_TYPE_TIME_NUMBER
			if ($dbField->dataType == SYM_TYPE_TIME_NUMBER & $compareKey == 'LIKE') {
				//TODO for now we just care about date not time
				$db = $dbInfo->getDatabase ();
				$format = $db->getFormatDateTime ( SYM_TYPE_DATE );
				$val = date ( $format, $val );
				$val = $prefix . $val . $subfix;
				$val = $dbInfo->dbQuoteData ( $val );
				$tmp [] = "FROM_UNIXTIME(" . $dbField->getNameWithAlias ( $dbInfo ) . ") $compare $val";
				continue;
			}
			
			$extWhere = '';
			if ($dbField->isBoolean() && !$val) {
				$extWhere = $dbField->getNameWithAlias ( $dbInfo ). ' IS NULL OR ';
			}
			if (! RStringHelper::isEmpty ( $prefix ) || ! RStringHelper::isEmpty ( $subfix )) {
				$val = $prefix . $val . $subfix;
			}
			
			if ($val === null) {
				$val = 'NULL';
				$compare = "IS";
			} else {
				$val = $dbInfo->dbQuoteData ( $val );
			}
			
			if ($extWhere) {
				$extWhere = '( ' .$extWhere . $dbField->getNameWithAlias ( $dbInfo ) . " $compare $val )";
			}
			else {
				$extWhere = $dbField->getNameWithAlias ( $dbInfo ) . " $compare $val";
			}
			$tmp [] = $extWhere;
		}
		$result = empty ( $tmp ) ? '' : sprintf ( $fmtsql, implode ( " $combineCondition ", $tmp ) );
		return $result;
	}
	
	/**
	 * Trim the string of public properties in DTO
	 *
	 * @param AbstractRubikDBObject $dbo
	 * @param string $charlist
	 * 
	 * @return AbstractRubikDBObject
	 */
	function trimString(&$rubikDBO, $charlist = null) {
		$dbInfo = RubikDBFactory::getDBInfo ( $rubikDBO );
		return $dbInfo->trimString ( $rubikDBO, $charlist );
	}
}
?>
